<?php


namespace app\admin\model;

use app\admin\model\Common;

class Password extends Common
{

    /**
     * 为了数据库的整洁，同时又不影响Model和Controller的名称
     * 我们约定每个模块的数据表都加上相同的前缀，比如CRM模块用crm作为数据表前缀
     */
    protected $name = 'admin_pwd_rule';


    /**
     * [getDataList 获取列表]
     * @return    [array]
     */
    public function getDataList()
    {
      $data = $this->order('id','asc')->find();
      if(!$data){
          return [];
      }
      return $data;
    }


    /**
     * 更新密码策略
     * @param $param
     * @return bool
     * @author Mr.Li
     * @create 2021-07-30 17:43
     */
    public function saveData(array $param): bool
    {

        try{
            $validate = new \app\admin\validate\Password();
            if (!$validate->scene('update')->check($param)) {
                $this->error = $validate->getError();
                return false;
            }
        }catch(\Exception $e) {
            $this->error = $e->getMessage();
            return false;
        }
        try {
            if($param['is_lock']){//锁定开启需要检测设置内容
                if (!$validate->scene('update_lock_option')->check($param)) {
                    $this->error = $validate->getError();
                    return false;
                }

                if($param['lock_option_type'] == 2){//固定设置需要检测次数和分钟数
                    if (!$validate->scene('update_lock_option_attempt')->check($param)) {
                        $this->error = $validate->getError();
                        return false;
                    }
                }
            }


            if(mb_strlen($param['pwd_min_length'],'utf8') > mb_strlen($param['pwd_max_length'],'utf8')){
                $this->error = '最小长度不能大于最大长度';
                return false;
            }

            //检测密码有效性
            $checkPwdMsg =  $this->checkPwdRule($param,$param['default_pwd']);
            if($checkPwdMsg){
                $this->error = $checkPwdMsg;
                return false;
            }
            $passwordModel = $this->order('id','asc')->find();
            $allowField = ['pwd_type','is_pwd_diff_account','is_diff_old_pwd','pwd_max_length','pwd_min_length','default_pwd','is_force_modify','is_lock','lock_attempt_count','lock_option_type','lock_option_attempt_count','lock_option_attempt_minute','multi_terminal_login'];
            if($passwordModel){
                $passwordModel->allowField($allowField)->save($param);
            }else{
                $this->allowField($allowField)->save($param);
            }
            return true;


        } catch(\Exception $e) {
            $this->error = '参数校验错误';
            return false;
        }
    }


    /**
     * 检测密码设置是否有效
     * @param $account
     * @param $oldPwd
     * @param $newPwd
     * @param $newPlainPwd
     * @return false|string|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author Mr.Li
     * @create 2021-07-30 11:56
     */
    public function checkPwd($account,$oldPwd,$newPwd,$newPlainPwd = '')
    {
        $ruleData = $this->order('id','asc')->find();
        if(!$ruleData){
            return false;
        }
        $account && $account = trim($account);
        $oldPwd && $oldPwd = trim($oldPwd);
        $newPwd && $newPwd = trim($newPwd);
        $returnMsg = '';
        $pwdType = $ruleData['pwd_type'];
        if($ruleData['is_pwd_diff_account']){
            if($account == $newPwd){
                $returnMsg = '账号和密码不能一样';
            }
        }
        if($returnMsg) return $returnMsg;
        if($ruleData['is_diff_old_pwd']){
            if($oldPwd == $newPwd){
                $returnMsg = '新密码不能和原密码一样';
            }
        }
        if($returnMsg) return $returnMsg;
        return $this->checkPwdRule($ruleData,$newPlainPwd);
    }


    /**
     * 获取默认密码
     * @author Mr.Li
     * @create 2021-07-30 11:41
     */
    public function getDefaultPwd()
    {
        $defalutPwd = $this->order('id','asc')->value('default_pwd');
        if(!$defalutPwd){
            return '123456a';
        }
        return $defalutPwd;
    }


    /**
     * 检测密码字段正确性
     * @param $ruleData
     * @param $pwd
     * @author Mr.Li
     * @create 2021-07-30 17:36
     */
    public function checkPwdRule($ruleData,$pwd)
    {
        $returnMsg = '';
        $specStr = '~!@#$%^&*()?_+';
        switch($ruleData['pwd_type'])
        {
            case '1':
                $ruleInfo = '/^[0-9]{'.$ruleData['pwd_min_length'].','.$ruleData['pwd_max_length'].'}$/';
                $returnMsg = '密码只能为长度为'.$ruleData['pwd_min_length'].'-'.$ruleData['pwd_max_length'].'的数字';
                break;
            case '2':
                $ruleInfo = '/^[a-zA-Z]{'.$ruleData['pwd_min_length'].','.$ruleData['pwd_max_length'].'}$/';
                $returnMsg = '密码只能为长度为'.$ruleData['pwd_min_length'].'的字母';
                break;
            case '3':
                $ruleInfo = '/^['.$specStr.']{'.$ruleData['pwd_min_length'].','.$ruleData['pwd_max_length'].'}$/';
                $returnMsg = '密码只能为长度为'.$ruleData['pwd_min_length'].'-'.$ruleData['pwd_max_length'].'的特殊字符';
                break;
            case '4':
                $ruleInfo = '/^(?![0-9]+$)(?![a-z]+$)[0-9a-z]{'.$ruleData['pwd_min_length'].','.$ruleData['pwd_max_length'].'}$/i';
                $returnMsg = '密码只能为长度为'.$ruleData['pwd_min_length'].'-'.$ruleData['pwd_max_length'].'的字母数字组合';
                break;
            case '5':
                $ruleInfo = '/^(?=.*[0-9])(?=.*['.$specStr.'])[0-9'.$specStr.']{'.$ruleData['pwd_min_length'].','.$ruleData['pwd_max_length'].'}$/i';
                $returnMsg = '密码只能为长度为'.$ruleData['pwd_min_length'].'-'.$ruleData['pwd_max_length'].'的数字特殊符号组合';
                break;
            case '6':
                $ruleInfo = '/^(?=.*[a-z])(?=.*['.$specStr.'])[a-z'.$specStr.']{'.$ruleData['pwd_min_length'].','.$ruleData['pwd_max_length'].'}$/i';
                $returnMsg = '密码只能为长度为'.$ruleData['pwd_min_length'].'-'.$ruleData['pwd_max_length'].'的字母特殊符号组合';
                break;
            case '7':
                $ruleInfo = '/^(?=.*[a-z])(?=.*\d)(?=.*['.$specStr.'])[a-z\d'.$specStr.']{'.$ruleData['pwd_min_length'].','.$ruleData['pwd_max_length'].'}$/i';
                $returnMsg = '密码只能为长度为'.$ruleData['pwd_min_length'].'-'.$ruleData['pwd_max_length'].'的字母数字特殊符号组合';
                break;
            default:
                break;
        }

        if(preg_match($ruleInfo,$pwd))
        {
            $returnMsg = '';
        }
        return $returnMsg;
    }


}
